thready

Otázka od: kevin33@post.cz

23. 9. 2002 22:07

zdravim,

mam problem ktery se budu snazit popsat: mam hlavni vlakno aplikace
a jeden thread ktery vypada asi takto:

execute:

OdesilaniDatNaComPort();

cas_odeslani := GetTickCount;
// cekam na data nebo na timeout
while ( (not odpoved_od_stroje) and (GetTickCount < (cas_odeslani +
timeout_mezi_odeslanim_a_prijmem) ) ) do sleep( 2 );

CekaniNaPredpokladanyPocetDatATestovaniJestliNenastalTimeout;

a ta posledni funkce normalne funguje, ale kdyz v hlavnim vlakne
spustim nejakou funkci (treba z menu), se smyckou ktera neco dela -
konkretne prekresleni obrazovky + dalsi veci tak v threadu nastane
timeout. a me ted neni jasne proc, kdyz ten thread prece bezi uplne
nezavisle na ostatnich vecech.

snazil jsem se z toho threadu odstranit vsechny kriticke sekce a
veskerou komunikaci s ostatnimi vlakny, ale timeout porad nastaval.

potreboval bych aby vlakno bezelo opravdu nezavisle na tom co se
deje ve zbytku aplikace

diky

ps: thread ma jeste roceduru ktera cte z com portu a nastavuje
promennou odpoved_od_stroje

Odpovedá: Tomáš Jantač

24. 9. 2002 8:42

Ahoj

Mas pravdu ze Thready pracuji nezavisle na jinych procesech, ale predstav si
jak procesor vykonava instrukce! On provadi nejakou cast programu (jedno
vlakno) a sam z niceho nic se do jineho procesu prepnout nemuze. To za nej
dela system, ktery vlastne spousti a koordinuje procesy. Takze System zavola
nejakou cast programu (pomoci nejake udalosti napr. onClick) a dokud
procedura obsluhujici tuto udalost neskonci, nebo nepovoli zpracovani
dalsich udalosti systemu probiha jeji zpracovani. Tzn. Pokud mas v nejake
casti hlavniho vlakna narocnejsi operace, je nutne je prolozit prikazem
Application.ProcessMessages nebo sleep(X). Kdyz tedy bude nejaka procedura
vykreslovat ve smycce neco na obrazovku je nutne do smycky vlozit jeden z
techto prikazu. Tim hlavni vlakno preda rizeni systemu, ten zpracuje
udalosti a preda rizeni dalsimu procesu. Procesy se takto mezi sebou
stridaji o systemovy cas a tak mohou bezet jakoby "paralelne".

V tvem pripade jde tedy pravdepodobne o to ze hlavni vlakno nenecha system
obslouzit ostatni procesy a ty se ke slovu dostanou az pozdeji, po TimeOutu

Pokud muzu radit, zkus se zamerit na funkce WaitForSingleMessage a
WaitForMultipleMessage s vyuzitim Eventu pri cekani a synchronizaci vlaken.

Osobne pri komunikaci po seriovem portu pouzivam komponentu afComPort od
Petra Vonese asi timto zpusobem:

....

procedure TMyCom.AfComPort1NonSyncEvent(Sender: TObject;
  EventKind: TAfCoreEvent; Data: Cardinal);
begin
    If (DATA AND Not(EV_RXCHAR)=0) AND (EventKind=ceLineEvent) then
setEvent(eventData);
end;

Constructor TMyCom.Create;
begin
    eventData := CreateEvent(nil,false,false,nil);
    eventShutDown := CreateEvent(nil,false,false,nil);
    afComPort.onNonSyncEvent:=AfComPort1NonSyncEvent;
end;

Procedure TMyCom.Execute;
Var MO : array [0..1] of THandle;
begin
    MO[0]:=eventData;
    MO[1]:=eventShutDown;
    Repeat
         Case WaitForMultipleObject(2,@MO,false,200) of
           WAIT_OBJECT_0 : Zpracuj data na portu!;
           WAIT_OBJECT_0+1: Bereak;
           WAIT_TIMEOUT : Pripadna obsluha pri zadne udalosti a
TimeOutu(200ms);
          end;
    until terminated;
end;

...

Tomas Jantac


>mam problem ktery se budu snazit popsat: mam hlavni vlakno aplikace
>a jeden thread ktery vypada asi takto:
>
>execute:
>
>OdesilaniDatNaComPort();
>
>cas_odeslani := GetTickCount;
>// cekam na data nebo na timeout
>while ( (not odpoved_od_stroje) and (GetTickCount < (cas_odeslani +
>timeout_mezi_odeslanim_a_prijmem) ) ) do sleep( 2 );
>
>CekaniNaPredpokladanyPocetDatATestovaniJestliNenastalTimeout;
>
>a ta posledni funkce normalne funguje, ale kdyz v hlavnim vlakne
>spustim nejakou funkci (treba z menu), se smyckou ktera neco dela -
>konkretne prekresleni obrazovky + dalsi veci tak v threadu nastane
>timeout. a me ted neni jasne proc, kdyz ten thread prece bezi uplne
>nezavisle na ostatnich vecech.
>
>snazil jsem se z toho threadu odstranit vsechny kriticke sekce a
>veskerou komunikaci s ostatnimi vlakny, ale timeout porad nastaval.
>
>potreboval bych aby vlakno bezelo opravdu nezavisle na tom co se
>deje ve zbytku aplikace

Odpovedá: Skopalik Slavomir

24. 9. 2002 9:16

Zalezi na casu toho timeoutu, normalne se cas prideluje po 5 - 20 ms.
Pokud je system zatizen, tak se ti muze stat, ze thread dostane cas
az po stovkach ms (extremene i po nekolikla desitkach sekund).

reseni:
1. doplnit vice CPU
2. zvetsit prioritu threadu
3. zvetsit prioritu aplikace
4. Napsat to jako kernel driver
5. Misto te divne smycky pouzit comtimeouts
6. Prodlouzit time outy (zpomalit komunikaci)

 Slavek

> a ta posledni funkce normalne funguje, ale kdyz v hlavnim vlakne
> spustim nejakou funkci (treba z menu), se smyckou ktera neco dela -
> konkretne prekresleni obrazovky + dalsi veci tak v threadu nastane
> timeout. a me ted neni jasne proc, kdyz ten thread prece bezi uplne
> nezavisle na ostatnich vecech.
>
> snazil jsem se z toho threadu odstranit vsechny kriticke sekce a
> veskerou komunikaci s ostatnimi vlakny, ale timeout porad nastaval.
>
> potreboval bych aby vlakno bezelo opravdu nezavisle na tom co se
> deje ve zbytku aplikace
>
> diky
>
> ps: thread ma jeste roceduru ktera cte z com portu a nastavuje
> promennou odpoved_od_stroje

Odpovedá: Karel Kral

24. 9. 2002 11:46

> Takze System zavola
> nejakou cast programu (pomoci nejake udalosti napr. onClick) a dokud
> procedura obsluhujici tuto udalost neskonci, nebo nepovoli zpracovani
> dalsich udalosti systemu probiha jeji zpracovani. Tzn. Pokud mas v nejake

Nejsem odbornik na thready, ale toto je zjevne blbost. Tak to fungovalo
za dob Windows 3.X, kdy byl kooperativni multitasking.

______________________________________________________
Karel Kral, vyvojar IT / IT developer
Purus, s.r.o., Cezavy 627, 664 56 Blucina, CZ
Tel: 547 235 000, 602 552 432, Fax: 547 231 203
E-Mail: mailto:kral@purus.cz, WWW: http://www.purus.cz
______________________________________________________

Odpovedá: Ondrej Kelle

24. 9. 2002 10:39

> Tzn. Pokud mas v nejake casti hlavniho vlakna narocnejsi
> operace, je nutne je prolozit prikazem
> Application.ProcessMessages nebo sleep(X). Kdyz tedy bude
> nejaka procedura vykreslovat ve smycce neco na obrazovku je
> nutne do smycky vlozit jeden z techto prikazu. Tim hlavni vlakno
> preda rizeni systemu, ten zpracuje udalosti a preda rizeni
> dalsimu procesu. Procesy se takto mezi sebou stridaji o
> systemovy cas a tak mohou bezet jakoby "paralelne".

To bolo v 16-bitovych Windows. Vo Win32 funguje preemptivny multitasking.
Ak mas v hlavnom threade programu pevnu slucku a nevolas
Application.ProcessMessages, prejavi sa to len v Tvojom programe - tym, ze
pocas vykonavania slucky nereaguje na spravy. Na ostatne procesy to nema
vplyv.

> V tvem pripade jde tedy pravdepodobne o to ze hlavni vlakno
> nenecha system obslouzit ostatni procesy a ty se ke slovu
> dostanou az pozdeji, po TimeOutu

Vo Win32 to nehrozi. Hovoris o 32-bitovych Windows?

TOndrej

Odpovedá: Dalibor Toman

24. 9. 2002 11:14

> Mas pravdu ze Thready pracuji nezavisle na jinych procesech, ale
predstav si
> jak procesor vykonava instrukce! On provadi nejakou cast programu
(jedno
> vlakno) a sam z niceho nic se do jineho procesu prepnout nemuze. To
za nej
> dela system, ktery vlastne spousti a koordinuje procesy. Takze
System zavola
> nejakou cast programu (pomoci nejake udalosti napr. onClick) a dokud
> procedura obsluhujici tuto udalost neskonci, nebo nepovoli
zpracovani
> dalsich udalosti systemu probiha jeji zpracovani. Tzn. Pokud mas v
nejake
> casti hlavniho vlakna narocnejsi operace, je nutne je prolozit
prikazem
> Application.ProcessMessages nebo sleep(X).

blbost. Od Win9x funguje multitasking ve windows nastesti uplne jinak.
Planovac uloh v systemu prideluje cas uloham a po dane dobe jim ho
odebere at aplikace chce nebo ne. Cili v Tvem prikladu s OnClickem se
muze stat, ze behem vykonavani jeho obsluhy bude stokrat aplikaci CPU
odejmut a znovu pridelen.

ProcessMessages je jen o tom, ze potrebujes donutit prekreslovaci
rutiny (stejneho threadu) aby obnovili zaobrazovany obsah okna (cili
vlastne jde o trosku zasmodrchane proste volani v ramci jednoho
threadu/procesu)

> V tvem pripade jde tedy pravdepodobne o to ze hlavni vlakno nenecha
system
> obslouzit ostatni procesy a ty se ke slovu dostanou az pozdeji, po
TimeOutu

preemptivni multitaskink je prave o tom, ze muzes mit X
aplikaci/threadu, kde v kazde pobezi prave jen prosta hloupa smycka
(while true do Inc(I);) a ve vsech apliacich se bude I vesele zvysovat
(ze bude CPU na 100% zatizene je samozrejme)

D. Toman

Odpovedá: Erik Salaj

25. 9. 2002 11:09

> potreboval bych aby vlakno bezelo opravdu nezavisle na tom co se
> deje ve zbytku aplikace

thready bezia nezavisle a komunikacia by mala fungovat. Obvykle
seriova komunikacia vyuziva eventy posielane Windowsom a koli
tomu sa zvykne pouzit jeden zvlastny thread na obsluhu eventov.
Programovanie seriovej komunikacie je dost komplikovana
zalezitost a s vynimkou trivialnych pripadov je vyhodnejsie
pouzit uz naprogramovane a odladene komponenty.

Erik

Odpovedá: Petr Vones

24. 9. 2002 20:39

From: <kevin33@post.cz>
> potreboval bych aby vlakno bezelo opravdu nezavisle na tom co se
> deje ve zbytku aplikace

Pak je nutne aby se neprovadely zadne synchronizace s hlavnim threadem
aplikace (napriklad TThread.Synchronize) a veskera komunikace byla realizovana
v tom threadu (ci vice threadech). Dale je vhodne nastavit u toho threadu
vyssi prioritu aby mu scheduler venoval vice pozornosti. Ani to vsak nezaruci
ze nedojde k nejake nahodne prodleve - Windows nejsou realtime OS. V praxi se
da takto dosahnout pomerne spolehlive reakce do desitek ms. Je-li treba kratsi
doba reakce je vhodne to realizovat pomoci nejakeho hardware zhotoveneho na
zakazku a ten pak ovladat z Windows.

Pouzivani Application.ProcessMessages je jinak samozrejme blbost, ale to uz tu
bylo receno.

Petr Vones